<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style>
    
  </style>
</head>
<body>
  
</body>
<script>

  // 5! = 5 * 4!
  //          4! = 4 * 3!
  //                   3! = 3 * 2!
  //                            2! = 2 * 1!
  //                                     1! = 1

  // 假设有一个功能叫fn，用来计算阶乘

  // fn(5) = 5 * fn(4)
  //             fn(4) = 4 * fn(3)
  //                         fn(3) = 3 * fn(2)
  //                                     fn(2) = 2 * fn(1)
  //                                                 fn(1) = 1

  // 公式
  // fn(n) = n * fn(n-1);
  // 递的终点，归的起点
  // fn(1) = 1

  // 计算任意数字的阶乘的功能
  // function fn( n ){
  //   if(n === 1){
  //     return 1;
  //   }else{
  //     return n * fn(n-1);
  //   }
  // }
  
  // console.log( fn(5) );

  // 利用了递归的思想

  // ==========
  
  // - 斐波那契数列
  //   - 1，1，2，3，5，8，13，21，...
  //   - 需求：计算第n位，是多少

  // 假设目前有一个功能叫fn，用来计算第n位的数字

  // 公式
  // fn(5) = fn(4) + fn(3);
  // fn(4) = fn(3) + fn(2);
  // fn(3) = fn(2) + fn(1);

  // fn(n) = fn(n-1) + fn(n-2);

  // 递的终点，归的起点
  // fn(2) = 1;
  // fn(1) = 1;

  // function fn( n ){
  //   if(n === 1 || n === 2){
  //     return 1;
  //   }else{
  //     return fn(n-1) + fn(n-2);
  //   }
  // }
  // console.log( fn(9) );


  // ===========

  // 计算两个数字的最大公约数
  // 约数：能被整除的数字
  // 公约数：能被两个数字一起整除的数
  // 最大公约数：最大的能被两个数字一起整除的数

  // 约数
  // 20：1，2，4，5，10，20
  // 约数
  // 30：1，2，3，5，6，10，15，30
  // 20和30的公约数
  // 1，2，5，10
  // 20和30的最大公约数
  // 10

  // 辗转相除法：
  // 将两个数字m和n取余：m % n
  //   余数如果为0，n，就是最大公约数
  //     如：30，15
  //   余数如果不为0，将 n 和余数继续取余，直到余数为0，本次的n，就是最大公约数

  // 30 % 20 === 10
  // 20 % 10 === 0
  // 10

  // 60 % 35 === 25
  // 35 % 25 === 10
  // 25 % 10 === 5
  // 10 % 5 === 0
  // 5

  // m, n

  function fn(m, n){
    var r = m % n;
    if(r === 0){
      return n;
    }else{
      return fn(n, r);
    }
  }

  console.log( fn(30,15) );

  console.log( fn(30,20) );
  
  console.log( fn(60,35) );
  
  console.log( fn(20, 30) );

</script>
</html>